﻿using OneDark.Git;
using OneDark.Update;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace OneDark.MsgQueue
{
    public class TaskControl
    {
        public TaskControl(int iTasks)
        {
            MaxThread = iTasks;
        }

        public int MaxThread { set; get; }
        private int iCurrnetTask = 0;
        private readonly object _locker_task = new object();     //这个锁，是用来同步读和写的；集合的读和写的；

        public bool Acquire()
        {
            lock (_locker_task)
            {
                return iCurrnetTask <= MaxThread;
            }
        }

        public void Release()
        {
            lock (_locker_task)
            {
                iCurrnetTask--;
            }
        }

        public bool IsTaskFull()
        {
            lock (_locker_task)
            {
                return iCurrnetTask >= ConfigRdr.MaxUpdateThreads;
            }
        }

        public int RunningTasks()
        {
            lock (_locker_task)
            {
                return iCurrnetTask;
            }
        }
    }

    public class ProducerConsumerQueue : IDisposable
    {
        //public Action<>
        private EventWaitHandle _wh = new AutoResetEvent(false);

        private ConcurrentQueue<GitProperty> _tasks = new ConcurrentQueue<GitProperty>();     //一旦队列有了消息就要通知我们的线程去消费；

        private TaskControl taskControl = new TaskControl(ConfigRdr.MaxUpdateThreads);

        /// <summary>
        /// 让线程跑起来
        /// </summary>
        public ProducerConsumerQueue()
        {
            Task.Run(() => Work());
        }

        /// <summary>
        /// 往线程中添加任务；一旦有了任务，就通知我们的消费者；
        /// 这里例子有很多问题滴呀；
        /// </summary>
        /// <param name="task"></param>
        public void EnqueueTask(GitProperty task)
        {
            _tasks.Enqueue(task);
            _wh.Set();
        }

        public ProducerConsumerQueue(List<GitProperty> gitProperties)
        {
            //_tasks = gitProperties.as;
        }

        public void EnqueueTasks(List<GitProperty> gitProperties)
        {
            gitProperties.ForEach(p => _tasks.Enqueue(p));
        }

        public void Work()
        {
            while (true)  //相当于就是在不断的去轮询我们的队列中的信息；让这个线程一直处于执行的状态，应为只有一个线程，不能让它执行一完一次任务只有就停止了
            {
                GitProperty task = null;
                if (_tasks.Count > 0) //队列中有数据，我们就从中取出数据；
                {
                    if (taskControl.Acquire())
                    {
                        _tasks.TryDequeue(out task);// 取出任务；
                        if (task == null) return;//任务为空就停止了；
                        Task.Run(() => RunGitPull(ref task));
                    }
                }

                if (task != null)
                {
                    //就取执行我们的任务；
                    Console.WriteLine("始终只有一个消费者：Task:{0} ThreadID{1} and now Quen length:{2}", task, Thread.CurrentThread.ManagedThreadId, _tasks.Count);
                    Task.Delay(1000);
                }
                else
                {
                    _wh.WaitOne(); //队列为空就等待
                }
            }
        }

        private void RunGitPull(ref GitProperty gitProperty)
        {
            Repository repository = new Repository()
            {
                Name = gitProperty.Project,
                Path = gitProperty.Path
            };
            repository.Open();
            string strBranch = repository.CurrentBranch().Name;
            string strRemote = repository.Remotes().FirstOrDefault().Name; //msg => { gitProperty.PullMsg = msg}
            //repository.Pull(strRemote, strBranch, msg => gitProperty.OnPullMsg?.Invoke(msg));
            repository.Pull(strRemote, strBranch, gitProperty.OnPullMsg);
            taskControl.Release();
        }

        public void Dispose()
        {
            EnqueueTask(null);      // Signal the consumer to exit.
            _wh.Close();            // Release any OS resources.
            Console.WriteLine("对象销毁完毕...");
        }
    }
}